import 'dart:math';
import 'dart:ui';
import 'package:flutter/cupertino.dart';
import 'package:kq_flutter_core_widget/utils/kq_screen_util.dart';
import '../../../resources/kq_pad_theme_colors.dart';
import '../kq_pda_chart_line_model.dart';
import 'package:path_drawing/path_drawing.dart';
import 'Kq_pad_line_monotone_x.dart';
import 'package:kq_flutter_core_widget/utils/ex/kq_ex.dart';

class KqPadChartMethod {
  //计算折线曲线运动路径
  static List getAnimationLinePath(Path path, List<KqPdaChartLineValue> points,
      List xList, List yList, double animationTime, bool isAnimationEnd) {
    PathMetrics ma = path.computeMetrics();
    Path newPath = Path();
    Path shadowPath = Path();
    int pointIndex = 0;
    Tangent? lastPoint;
    while (ma.iterator.moveNext()) {
      PathMetric mm = ma.iterator.current;
      newPath.addPath(
          mm.extractPath(0, animationTime * mm.length), Offset.zero);
      shadowPath.addPath(
          mm.extractPath(0, animationTime * mm.length), Offset.zero);
      lastPoint = mm.getTangentForOffset(animationTime * mm.length);
      pointIndex = (animationTime /
              ((xList[1] - xList.first) / (xList.last - xList.first)))
          .ceil();
      break;
    }
    // List<Path> pathArray = KqPadChartMethod.getPathArray(
    //     path, pointIndex, points.length, animationTime);
    pointIndex = isAnimationEnd ? xList.length : pointIndex;
    shadowPath.lineTo(lastPoint?.position.dx ?? xList.last, yList.last);
    shadowPath.lineTo(xList.first, yList.last);
    shadowPath.close();
    return [[], shadowPath, newPath, pointIndex];
  }

  //得到各段的路径,计算存在问题暂时不使用
  static List<Path> getPathArray(
      Path masterPath, int pointIndex, int allPoints, double animationTime) {
    PathMetrics ma = masterPath.computeMetrics();
    List<Path> pathArray = [];
    while (ma.iterator.moveNext()) {
      PathMetric mm = ma.iterator.current;
      double first = 0;
      for (var i = 1; i < pointIndex; i++) {
        double nowRadio = i / (allPoints - 1);
        pathArray
            .add((mm.extractPath(first * mm.length, nowRadio * mm.length)));
        first = nowRadio;
      }
      double last = (pointIndex - 1) / (allPoints - 1);
      if (last < animationTime) {
        pathArray
            .add((mm.extractPath(last * mm.length, animationTime * mm.length)));
      }
      break;
    }
    return pathArray;
  }

  //计算柱状运动路径
  static Path getAnimationBarPath(
      Path path, double animationTime, bool isAnimationEnd) {
    PathMetrics ma = path.computeMetrics();
    Path newPath = Path();
    while (ma.iterator.moveNext()) {
      PathMetric mm = ma.iterator.current;
      newPath.addPath(
          mm.extractPath(0, animationTime * mm.length), Offset.zero);
      break;
    }
    if (isAnimationEnd) {
      newPath = path;
    }
    return newPath;
  }

  ///计算曲线坐标
  static Path getSmoothLinePath(List<KqPdaChartLineValue> values) {
    List<Point> points = [];
    values.map((KqPdaChartLineValue e) {
      if (e.yValue.isNotNullOrEmpty) {
        points.add(Point(e.xPoint, e.yPoint));
      }
    }).toList();
    var targetPoints = <Point>[];
    targetPoints.addAll(points);
    targetPoints.add(Point(
        points[points.length - 1].x * 2, points[points.length - 1].y * 2));
    double? x0, y0, x1, y1, t0;
    var path = Path();
    for (int i = 0; i < targetPoints.length; i++) {
      double? t1;
      var x = targetPoints[i].x;
      var y = targetPoints[i].y;
      if (x == x1 && y == y1) break;
      switch (i) {
        case 0:
          path.moveTo(x as double, y as double);
          break;
        case 1:
          break;
        case 2:
          t1 = KqPadMonotoneX.slope3(
              x0!, y0!, x1!, y1!, x as double, y as double);
          KqPadMonotoneX.point(path, x0, y0, x1, y1,
              KqPadMonotoneX.slope2(x0, y0, x1, y1, t1), t1);
          break;
        default:
          t1 = KqPadMonotoneX.slope3(
              x0!, y0!, x1!, y1!, x as double, y as double);
          KqPadMonotoneX.point(path, x0, y0, x1, y1, t0!, t1);
      }
      x0 = x1;
      y0 = y1;
      x1 = x as double;
      y1 = y as double;
      t0 = t1;
    }
    return path;
  }

  //绘制X轴Y轴，Y轴分割线,Y轴上文案内容，X轴上文案内容
  static void drawXYAxisPath({
    required Canvas canvas,
    required Paint paint,
    required Color axisColor,
    required List xList,
    required List yList,
    required double xRight,
    required bool isDivide,
    required Color dividerColor,
    required bool hintLineSolid,
    required List crossShowList,
    required TextStyle yStyle,
    required TextStyle xStyle,
    required List yValue,
    required List xValue,
    required double yAisTop,
    double? angle,
    List? yRightValue,
    String? unit,
    TextStyle? unitStyle,
    String? rightUnit,
    TextStyle? rightUnitStyle,
    double initialPointX = 0,
    double? yLabelDistance,
    double? yRightLabelDistance,
    double? xLabelDistance,
    double? xAngleDistance,
  }) {
    paint.color = axisColor;
    Path horizontalPath = Path();
    horizontalPath.moveTo(xList.first - initialPointX, yList.last);
    horizontalPath.lineTo(xList.last + xRight, yList.last);
    canvas.drawPath(horizontalPath, paint);

    Path verticalPath = Path();
    verticalPath.moveTo(xList.first - initialPointX, yAisTop);
    verticalPath.lineTo(xList.first - initialPointX, yList.last);
    canvas.drawPath(verticalPath, paint);

    if (yRightValue.isNotNullOrEmpty) {
      Path verticalRightPath = Path();
      verticalRightPath.moveTo(xList.last, yAisTop);
      verticalRightPath.lineTo(xList.last, yList.last);
      canvas.drawPath(verticalRightPath, paint);
      KqPadChartMethod.drawRightYValue(
          canvas: canvas,
          yList: yList,
          yValue: yRightValue!,
          xList: xList,
          xRight: xRight,
          yStyle: yStyle,
          yRightLabelDistance: yRightLabelDistance);
    }
    KqPadChartMethod.drawYValue(
        canvas: canvas,
        yValue: yValue,
        xList: xList,
        yList: yList,
        yStyle: yStyle,
        initialPointX: initialPointX,
        yLabelDistance: yLabelDistance);
    KqPadChartMethod.drawXValue(
        canvas: canvas,
        crossShowList: crossShowList,
        xValue: xValue,
        xList: xList,
        yList: yList,
        angle: angle,
        xStyle: xStyle,
        xAngleDistance: xAngleDistance,
        xLabelDistance: xLabelDistance);

    if (unit != null) {
      var textUnit = TextPainter(
          textAlign: TextAlign.right,
          ellipsis: '.',
          maxLines: 1,
          text: TextSpan(
              text: unit,
              style: unitStyle ??
                  TextStyle(fontSize: 6.sp, color: KqPadThemeColors.textBF)),
          textDirection: TextDirection.ltr)
        ..layout();
      var textY = TextPainter(
          textAlign: TextAlign.left,
          ellipsis: '.',
          maxLines: 1,
          text: TextSpan(text: yValue.last, style: yStyle),
          textDirection: TextDirection.ltr)
        ..layout();
      textUnit.paint(
          canvas, Offset(xList.first - initialPointX - textY.width - 6.r, 0));
    }

    if (rightUnit != null) {
      var textUnit = TextPainter(
          textAlign: TextAlign.left,
          ellipsis: '.',
          maxLines: 1,
          text: TextSpan(
              text: rightUnit,
              style: rightUnitStyle ??
                  TextStyle(fontSize: 6.sp, color: KqPadThemeColors.textBF)),
          textDirection: TextDirection.ltr)
        ..layout();
      var textRY = TextPainter(
          textAlign: TextAlign.left,
          ellipsis: '.',
          maxLines: 1,
          text: TextSpan(text: yRightValue!.last, style: yStyle),
          textDirection: TextDirection.ltr)
        ..layout();
      textUnit.paint(canvas,
          Offset(xList.last + textRY.width + 6.r + xRight - textUnit.width, 0));
    }

    if (isDivide == true) {
      paint.color = dividerColor;
      for (int i = 0; i < yList.length - 1; i++) {
        Path dividerPath = Path();
        dividerPath.moveTo(xList.first - initialPointX, yList[i]);
        dividerPath.lineTo(xList.last + xRight, yList[i]);
        if (hintLineSolid) {
          canvas.drawPath(dividerPath, paint);
        } else {
          canvas.drawPath(
            dashPath(
              dividerPath,
              dashArray: CircularIntervalList<double>(<double>[4.0, 2.0]),
            ),
            paint,
          );
        }
      }
    }
  }

  ///绘制平均线
  static void drawAvgLine({
    required Canvas canvas,
    required Paint paint,
    required List avgYPointList,
    required bool isAvg,
    required List xList,
    required double xRight,
    List<Color>? avgColors,
    required List avgValues,
    required bool isAvgValue,
    required bool hintAvgLineSolid,
    double initialPointX = 0,
  }) {
    if (isAvg == true) {
      for (int i = 0; i < avgYPointList.length; i++) {
        if (avgColors != null && avgColors.length > i) {
          paint.color = avgColors[i];
        } else {
          paint.color = KqPadThemeColors.textLightBlue;
        }
        Path dividerPath = Path();
        dividerPath.moveTo(xList.first - initialPointX, avgYPointList[i]);
        dividerPath.lineTo(xList.last + xRight, avgYPointList[i]);
        if (hintAvgLineSolid) {
          canvas.drawPath(dividerPath, paint);
        } else {
          canvas.drawPath(
            dashPath(
              dividerPath,
              dashArray: CircularIntervalList<double>(<double>[4.0, 2.0]),
            ),
            paint,
          );
        }
      }
      if (isAvgValue == true) {
        double xRightPoint = xList.last + xRight;
        for (var i = 0; i < avgValues.length; i++) {
          String value = avgValues[i];
          var avgText = TextPainter(
              textAlign: TextAlign.right,
              ellipsis: '.',
              maxLines: 1,
              text: TextSpan(
                  text: '平均值:$value',
                  style: TextStyle(
                      fontSize: 10.sp, color: KqPadThemeColors.text59)),
              textDirection: TextDirection.ltr)
            ..layout();
          avgText.paint(canvas, Offset(xRightPoint - avgText.size.width, 0));
          xRightPoint = xRightPoint - avgText.size.width - 4.r;

          if (avgColors != null && avgColors.length > i) {
            paint.color = avgColors[i];
          } else {
            paint.color = KqPadThemeColors.textLightBlue;
          }
          Path dividerPath = Path();
          dividerPath.moveTo(xRightPoint, 8.sp);
          dividerPath.lineTo(xRightPoint - 10.r, 8.sp);
          if (hintAvgLineSolid) {
            canvas.drawPath(dividerPath, paint);
          } else {
            canvas.drawPath(
              dashPath(
                dividerPath,
                dashArray: CircularIntervalList<double>(<double>[4.0, 2.0]),
              ),
              paint,
            );
          }
          xRightPoint = xRightPoint - 10.r - 20.r;
        }
      }
    }
  }

  ///绘制右y轴文案
  static void drawRightYValue({
    required Canvas canvas,
    required List yValue,
    required List xList,
    required List yList,
    required double xRight,
    required TextStyle yStyle,
    double? yRightLabelDistance,
  }) {
    for (int i = 0; i < yValue.length; i++) {
      var textY = TextPainter(
          textAlign: TextAlign.left,
          ellipsis: '.',
          maxLines: 1,
          text: TextSpan(text: yValue[i], style: yStyle),
          textDirection: TextDirection.ltr)
        ..layout();
      textY.paint(
          canvas,
          Offset(xList.last + (yRightLabelDistance ?? 6.r) + xRight,
              yList[i] - textY.height / 2));
    }
  }

  /// 绘制正常y轴文本
  static void drawYValue({
    required Canvas canvas,
    required List yValue,
    required List xList,
    required List yList,
    required TextStyle yStyle,
    double initialPointX = 0,
    double? yLabelDistance,
  }) {
    for (int i = 0; i < yValue.length; i++) {
      var textY = TextPainter(
          textAlign: TextAlign.right,
          ellipsis: '.',
          maxLines: 1,
          text: TextSpan(text: yValue[i], style: yStyle),
          textDirection: TextDirection.ltr)
        ..layout();
      textY.paint(
          canvas,
          Offset(
              xList.first -
                  initialPointX -
                  textY.width -
                  (yLabelDistance ?? 6.r),
              yList[i] - textY.height / 2));
    }
  }

  /// 绘制x轴文本
  static void drawXValue({
    required Canvas canvas,
    required List crossShowList,
    required List xValue,
    required List xList,
    required List yList,
    required TextStyle xStyle,
    double? angle,
    double? xLabelDistance,
    double? xAngleDistance,
  }) {
    if (xValue.length > 1) {
      if (angle != null && angle > 0) {
        canvas.save();
        double radians = pi * (angle / 180);
        double height = yList.last;
        double sinValue = sin(radians);
        double cosValue = cos(radians);
        double tanValue = tan(radians);
        canvas.translate(
            (height * sinValue + xList.first * tanValue * sinValue),
            height - (height * cosValue + xList.first * cosValue * sinValue));
        canvas.rotate(radians);
        double interval = xList[1] - xList.first;
        for (int i = 0; i < xList.length; i++) {
          if (xValue.length > i) {
            var textX = TextPainter(
                textAlign: TextAlign.center,
                ellipsis: '.',
                maxLines: 1,
                text: TextSpan(text: xValue[i], style: xStyle),
                textDirection: TextDirection.ltr)
              ..layout();
            textX.paint(
                canvas,
                Offset(
                    interval * cosValue * i +
                        xList.first -
                        (xAngleDistance ?? 6.r),
                    yList.lastOrNull -
                        interval * i * sinValue +
                        (xLabelDistance ?? 6.r)));
          }
        }
        canvas.restore();
      } else {
        if (crossShowList.isNotEmpty) {
          for (int i = 0; i < crossShowList.length; i++) {
            int index = crossShowList[i];
            var textX = TextPainter(
                textAlign: TextAlign.center,
                ellipsis: '.',
                maxLines: 1,
                text: TextSpan(text: xValue[index], style: xStyle),
                textDirection: TextDirection.ltr)
              ..layout();
            textX.paint(
                canvas,
                Offset(xList[index] - textX.width / 2,
                    yList.last + (xLabelDistance ?? 6.r)));
          }
        } else {
          for (int i = 0; i < xList.length; i++) {
            if (xValue.length > i) {
              var textX = TextPainter(
                  textAlign: TextAlign.center,
                  ellipsis: '.',
                  maxLines: 1,
                  text: TextSpan(text: xValue[i], style: xStyle),
                  textDirection: TextDirection.ltr)
                ..layout();
              textX.paint(
                  canvas,
                  Offset(xList[i] - textX.width / 2,
                      yList.last + (xLabelDistance ?? 6.r)));
            }
          }
        }
      }
    } else {
      if (xValue.isNotEmpty) {
        var textX = TextPainter(
            textAlign: TextAlign.center,
            ellipsis: '.',
            maxLines: 1,
            text: TextSpan(text: xValue.first, style: xStyle),
            textDirection: TextDirection.ltr)
          ..layout();
        textX.paint(
            canvas,
            Offset(
                xList.first + (xList.last - xList.first) / 2 - textX.width / 2,
                yList.last + (xLabelDistance ?? 6.r)));
      }
    }
  }

  ///绘制自定义的分割线
  static void drawCustomDividerLine(Canvas canvas, List xList, List yList,
      {List<KqPdaDividerValue>? xDivider, List<KqPdaDividerValue>? yDivider}) {
    var paint = Paint()..style = PaintingStyle.stroke;
    if (xDivider.isNotNullOrEmpty) {
      for (var i = 0; i < xDivider!.length; i++) {
        Path path = Path();
        KqPdaDividerValue item = xDivider[i];
        paint.strokeWidth = item.lineWidth;
        paint.color = item.dividerColor;
        path.moveTo(item.valueDouble, yList.first);
        path.lineTo(item.valueDouble, yList.last);

        if (item.isDottedLine) {
          canvas.drawPath(
            dashPath(
              path,
              dashArray: CircularIntervalList<double>(<double>[4.0, 2.0]),
            ),
            paint,
          );
        } else {
          canvas.drawPath(path, paint);
        }
      }
    }
    if (yDivider.isNotNullOrEmpty) {
      for (var i = 0; i < yDivider!.length; i++) {
        Path path = Path();
        KqPdaDividerValue item = yDivider[i];
        paint.strokeWidth = item.lineWidth;
        paint.color = item.dividerColor;
        path.moveTo(xList.first, item.valueDouble);
        path.lineTo(xList.last, item.valueDouble);
        if (item.isDottedLine) {
          canvas.drawPath(
            dashPath(
              path,
              dashArray: CircularIntervalList<double>(<double>[4.0, 2.0]),
            ),
            paint,
          );
        } else {
          canvas.drawPath(path, paint);
        }
      }
    }
  }
}
